#!/usr/bin/env bash
# Copyright (c) 2021-2022 maminjie <canpool@163.com>
# SPDX-License-Identifier: MulanPSL-2.0

method_def gec


__gec_token=""
__gec_id=""
__gec_passwd=""


usage_gec() {
    module_usage "gec" "gitee command-line tool"
}

do_gec() {
    module_do "gec" "$@"
}

gec_usage_help() {
    module_usage_help gec
}

# gec_do_help subcmd
gec_do_help() {
    module_do_help gec "$1"
}

# __gec_get_subcmd cmd
#   Get the fullname of cmd
# Returns:
#   "" or fullname
__gec_get_subcmd() {
    local cmd=""
    case "${1}" in
        "h"|"help")
            cmd="help"
            ;;
        "push")
            cmd="push"
            ;;
        "fork")
            cmd="fork"
            ;;
        "del"|"delete")
            cmd="delete"
            ;;
        "pr"|"createpr")
            cmd="createpr"
            ;;
        "cpr"|"commentpr")
            cmd="commentpr"
            ;;
        "l"|"ls"|"list")
            cmd="list"
            ;;
        *)
            ;;
    esac
    echo "$cmd"
}


gec_init() {
    if [ -z "$__gec_token" ]; then
        __gec_token=$(setting_get gitee token)
        gitee_init "$__gec_token"
    fi
    if [ -z "$__gec_id" ]; then
        __gec_id=$(setting_get gitee id)
    fi
}

# gec_check_repo repo
#   Check personal repo
# Returns:
#   1 - exist
#   0 - nonexist
gec_check_repo() {
    local git_url="https://gitee.com/$__gec_id/$1"
    local result=$(gitee_get_one_repo "$__gec_id" "$1")
    if [ -n "$result" ]; then
        return 1
    fi
    return 0
}

# gitee_get_contents owner repo path ref
#   Get the content under the specific path of the owner/repo
# Params:
#   path - the file path
#   ref - branch, tag or commit
# Returns:
#   "" or contents
gec_get_contents() {
    gec_init
    gitee_get_contents "$@"
}

# gitee_get_trees owner repo sha [recursive]
#   Get the directory trees
# Params:
#   sha - branch, tag, commit
#   recursive - assign 1 to get the directory recursively
# Returns:
#   "" or trees
gec_get_trees() {
    gec_init
    gitee_get_trees "$@"
}

# gec_get_path owner repo path ref
gec_get_path() {
    gec_init
    gitee_get_path "$@"
}

# gec_get_branches owner repo
gec_get_branches() {
    gec_init
    gitee_get_branches "$@"
}

# gec_get_user_repos username
gec_get_user_repos() {
    gec_init
    gitee_get_user_repos $@
}

# gec_get_org_repos org
gec_get_org_repos() {
    gec_init
    gitee_get_org_repos "$@"
}

# gec_get_project_labels owner repo
gec_get_project_labels() {
    gec_init
    gitee_get_project_labels "$@"
}

# gec_pushcode comments
gec_pushcode() {
    if [ -z "$__gec_passwd" ]; then
        __gec_passwd=$(setting_get gitee passwd)
        if [ -z "$__gec_passwd" ]; then
            # == read -s -p ...
            stty -echo
            read -p "Password for gitee: " __gec_passwd
            stty echo
        fi
    fi
    git add .
    git commit -m "$1"
    expect -c "
    set timeout -1
    spawn git push
    expect {
    \"*Username*\" {send \"${__gec_id}\r\";exp_continue}
    \"*Password*\" {send \"${__gec_passwd}\r\";exp_continue}
    }
    "
}

# gec_createpr owner repo comments url [branch] [body]
gec_createpr() {
    local branch="$5"
    local body="$6"
    local curbranch=$(git_curbranch)
    if [ -z "$branch" ]; then
        branch=$curbranch
    fi
    local __pr_url__=""
    gitee_create_pr "$1" "$2" "$3" "$__gec_id" "$curbranch" "$branch" __pr_url__ "$body"
    eval $4=\"$__pr_url__\"
}

gec_usage_push() {
printf "push: Auto push code, including push, pr.

Usage:
    ${PROG} gec push owner repo [comments] [branch] [prbody]

Params:
    owner - The upstream owner of package, as: src-openeuler
    comments - (optional) default is \"Package init\", and as the title of pr
    branch - (optional) target branch, default is current branch of gitrepository
    prbody - (optional) the pr description

Progress:
    git add .
    git commit -m \"{comments}\"
    git push
    create pr from mine/repo/currentbranch to owner/repo/branch
\n"
}

# gec_do_push owner repo [comments] [branch] [prbody]
gec_do_push() {
    if [ $# -lt 2 ]; then
        gec_usage_push; exit
    fi
    local owner=$1
    local repo=$2
    local comments="$3"
    local branch=$4
    local prbody="$5"
    if [ -z "$comments" ]; then
        comments="Package Init"
    fi
    gec_init
    gec_pushcode "$comments"
    local url=""
    gec_createpr "$owner" "$repo" "$comments" url "$branch" "$prbody"
    if [ -n "$url" ]; then
        echo "$url"
    fi
}

gec_usage_delete() {
printf "delete (del): Delete the repo of owner from gitee

Usage:
    ${PROG} gec del owner repos
\n"
}

# gec_do_delete owner repos
gec_do_delete() {
    if [ $# -ne 2 ]; then
        gec_usage_delete; exit
    fi
    local owner=$1
    local repos=$(get_list "$2")

    gec_init
    for repo in $repos; do
        echo -n "delete $owner/$repo: "
        gitee_delete_repo "$owner" "$repo"
        if [ $? -ne 0 ]; then
            color_print "$CLR_RED" "failed"
        else
            color_print "$CLR_GREEN" "success"
        fi
    done
}

gec_usage_fork() {
printf "fork: Fork the repo from upstream

Usage:
    ${PROG} gec fork owner repos [organization]
\n"
}

# gec_do_fork owner repos [organization]
gec_do_fork() {
    if [ $# -lt 2 ]; then
        gec_usage_fork; exit
    fi
    local owner=$1
    local repos=$(get_list "$2")

    gec_init
    for repo in $repos; do
        echo -n "forking $repo: "
        gec_check_repo "$repo"
        if [ $? -eq 0 ]; then
            gitee_fork_repo "$owner" "$repo" $3
            if [ $? -ne 0 ]; then
                color_print "$CLR_RED" "failed"
                continue
            else
                color_print "$CLR_GREEN" "success"
            fi
        else
            color_print "$CLR_BLUE" "maybe exist"
        fi
    done
}

gec_usage_createpr() {
printf "createpr (pr): Create PR to upstream repo

Usage:
    ${PROG} gec pr owner repo title [srcbranch] [dstbranch] [body]

Params:
    xxxbranch - (optional) if the current directory is a git repository,
                the default is the current branch, otherwise the default is master
    body - (optional) the pr description

Examples:
    ${PROG} gec pr maminjie test \"test pr with body\" master develop \"pr body\"
    ${PROG} gec pr maminjie test \"test pr without body\" master develop   # maminjie:develop -> maminjie:master
    ${PROG} gec pr src-openeuler test \"test pr\"                          # maminjie:master -> src-openeuler:master
\n"
}

# gec_do_createpr owner repo title [srcbranch] [dstbranch] [body]
gec_do_createpr() {
    if [ $# -lt 3 ]; then
        gec_usage_createpr; exit
    fi
    gec_init
    local owner="$1"
    local repo="$2"
    local title="$3"
    local sbranch="$4"
    local dbranch="$5"
    local body="$6"
    if [ -z "$sbranch" ]; then
        git_check_localrepo
        if [ $? -eq 0 ]; then
            sbranch=$(git_curbranch)
        fi
    fi
    if [ -z "$dbranch" ]; then
        dbranch="$sbranch"
    fi
    local __url=""
    gitee_create_pr "$owner" "$repo" "$title" "$__gec_id" "$sbranch" "$dbranch" __url "$body"
    if [ -n "$__url" ]; then
        echo "$__url"
    fi
}

gec_usage_commentpr() {
printf "commentpr (cpr): Comment pull request

Usage:
    ${PROG} gec commentpr owner repos number comments
    ${PROG} gec commentpr urls comments

Params:
    repos - If it is a list (string list or list file) of repositories,
            then all repos use the same number and comments
    urls - pr url list (string list or list file),
            url as: \"https://gitee.com/{owner}/{repo}/pulls/{number}\"
\n"
}

# __gec_do_commentpr owner repo number comments
__gec_do_commentpr() {
    local owner=$1
    local repo="$2"
    local number="$3"
    local comments="$4"
    echo -n "comment PR $owner/$repo/$number \"$comments\": "
    gitee_set_pr_comment "$owner" "$repo" "$number" "$comments"
    if [ $? -eq 0 ]; then
        color_print "$CLR_GREEN" "success"
    else
        color_print "$CLR_RED" "failed"
    fi
}

# gec_do_commentpr owner repos number comments
# gec_do_commentpr urls comments
gec_do_commentpr() {
    local owner=""
    local number=""
    local comments=""

    gec_init
    if [ $# -eq 2 ]; then
        local urls=$(get_list "$1")
        comments="$2"
        local repo=""
        # https://gitee.com/maminjie/ola/pulls/1
        for url in $urls; do
            eval $(echo "$url" | awk -F "/" '{
                if (NF >= 7) {
                    printf("owner=%s;repo=%s;number=%s;", $(NF-3), $(NF-2), $NF)
                }
            }')
            if [[ -z "$owner" || -z "$repo" || -z "$number" ]]; then
                continue
            fi
            __gec_do_commentpr "$owner" "$repo" "$number" "$comments"
        done
    elif [ $# -eq 4 ]; then
        owner=$1
        local repos=$(get_list "$2")
        number="$3"
        comments="$4"
        for repo in $repos; do
            __gec_do_commentpr "$owner" "$repo" "$number" "$comments"
        done
    else
        gec_usage_commentpr; exit
    fi
}

gec_usage_list() {
printf "list (l, ls): List the infos from gitee

usage:
    ${PROG} gec list [args...]

optional arguments:
    -h, --help          show this help message and exit
    -b OWNER/REPO       list the branches of owner/repo
    -u USER             list the repos of user
    -o ORG              list the repos of org
\n"
}

gec_do_list() {
    local ARGS=$(getopt -o "hb:u:o:" -l "help" -n "list" -- "$@")
    eval set -- "${ARGS}"

    local owner=""
    local repo=""

    while true; do
        case "${1}" in
            -h|--help)
                gec_usage_list; exit
                ;;
            -b)
                owner="${2%/*}"; repo="${2#*/}"
                gec_get_branches $owner $repo; exit
                ;;
            -u)
                gec_get_user_repos "$2"; exit
                ;;
            -o)
                gec_get_org_repos "$2"; exit
                ;;
            --)
                shift; break
                ;;
        esac
    done

    if [ $# -eq 0 ]; then
        gec_usage_list; exit
    fi
}
